package com.atguigu.completablefuture;

import java.util.ArrayList;
import java.util.concurrent.*;

/**
 * @author wk
 * @create 2021-09-02 17:17
 * 测试异步编排
 */
public class CompletableFutureDemo2 {
    public static void main(String[] args) {
        // 创建异步对象
        // runAsync方法 无返回值 有两个重载的方法
        // 1. public static CompletableFuture<Void> runAsync(Runnable runnable)
        // 第一个参数为实现Runnable接口的实现类 第二个参数是线程池
        // 2.public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
        // 自定义线程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                5,// 核心线程数
                10,// 最大线程数
                5L, //空闲线程的存活时间
                TimeUnit.SECONDS,// 时间单位
                new LinkedBlockingQueue<>(10),// 工作队列
                Executors.defaultThreadFactory(),// 线程工厂
                new ThreadPoolExecutor.AbortPolicy()// 默认的拒绝策略 抛异常 阻止系统正常运行
        );
        // CompletableFuture
        //  1.创建线程无返回值
        CompletableFuture.runAsync(() -> { // 使用的是Runnable   如果有异常只能将异常自己处理 不可以抛出来
            System.out.println(Thread.currentThread().getName());
        }, threadPoolExecutor).whenComplete((t, u) -> { // 计算完成时回调方法
            // 两个参数 第一个接收上一个任务的返回值
            System.out.println("接收上一个任务的返回值" + t);
            // 第二个参数接收上一个任务的异常
            System.out.println("接收上一个任务的异常" + u);
        });
        // 2.创建线程有返回值 参数二使用自定义线程池 如果不写则使用默认的线程池
        CompletableFuture.supplyAsync(() -> {// 底层使用的是Callable 有返回值 如果有异常也可以将异常抛到主线程中
            System.out.println(Thread.currentThread().getName());
            return "supplyAsync";
        }, threadPoolExecutor).whenComplete((t, u) -> { // 上一个任务和当前任务使用同一个线程
            // 两个参数 第一个接收上一个任务的返回值
            System.out.println("接收上一个任务的返回值" + t);
            // 第二个参数接收上一个任务的异常
            System.out.println("接收上一个任务的异常" + u);
        });
        CompletableFuture.supplyAsync(() -> {
            return "有返回值";
        }, threadPoolExecutor).whenCompleteAsync((t, u) -> { //whenCompleteAsync 会重新从线程池中获取获取新的线程执行当前任务
            // 两个参数 第一个接收上一个任务的返回值
            System.out.println("接收上一个任务的返回值" + t);
            // 第二个参数接收上一个任务的异常
            System.out.println("接收上一个任务的异常" + u);
        }, threadPoolExecutor).exceptionally((u) -> { //只能处理异常
            System.out.println(u);// 接收上一个任务的异常 有则处理 否则不处理
            return "异常处理成功"; // 返回异常处理结果
        });
    }
}
